package db

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/yourusername/rss-reader-ai/internal/config"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// =====================================================
// 全局数据库实例
// =====================================================

var DB *gorm.DB

// =====================================================
// 数据库连接函数
// =====================================================

// InitDB 初始化数据库连接
// 参数:
//   - cfg: 数据库配置
// 返回:
//   - *gorm.DB: GORM 数据库实例
//   - error: 错误信息
func InitDB(cfg *config.DatabaseConfig) (*gorm.DB, error) {
	// 1. 获取 DSN(Data Source Name)
	dsn := cfg.GetDSN()

	// 2. 配置 GORM 日志级别
	var logLevel logger.LogLevel
	switch config.GlobalConfig.Log.Level {
	case "debug":
		logLevel = logger.Info // 显示所有 SQL 语句
	case "info":
		logLevel = logger.Warn // 只显示慢查询和错误
	default:
		logLevel = logger.Error // 只显示错误
	}

	// 3. 打开数据库连接
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logLevel),
		// 禁用外键约束(因为我们在 SQL 中已经定义了外键)
		DisableForeignKeyConstraintWhenMigrating: true,
		// 跳过默认事务(提升性能)
		SkipDefaultTransaction: true,
		// 预编译 SQL(提升性能)
		PrepareStmt: true,
	})

	if err != nil {
		return nil, fmt.Errorf("连接数据库失败: %w", err)
	}

	// 4. 获取底层的 sql.DB 对象(用于配置连接池)
	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("获取数据库实例失败: %w", err)
	}

	// 5. 配置连接池
	// SetMaxIdleConns: 设置空闲连接池中连接的最大数量
	sqlDB.SetMaxIdleConns(cfg.MaxIdleConns)

	// SetMaxOpenConns: 设置打开数据库连接的最大数量
	sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)

	// SetConnMaxLifetime: 设置连接的最大生存时间
	// 超过这个时间,连接将被关闭并重新创建
	sqlDB.SetConnMaxLifetime(cfg.GetConnMaxLifetime())

	// 6. 测试数据库连接
	if err := sqlDB.Ping(); err != nil {
		return nil, fmt.Errorf("数据库连接测试失败: %w", err)
	}

	// 7. 保存到全局变量
	DB = db

	log.Printf("✅ 数据库连接成功: %s:%d/%s", cfg.Host, cfg.Port, cfg.Database)

	return db, nil
}

// =====================================================
// 数据库关闭函数
// =====================================================

// CloseDB 关闭数据库连接
func CloseDB() error {
	if DB == nil {
		return nil
	}

	sqlDB, err := DB.DB()
	if err != nil {
		return fmt.Errorf("获取数据库实例失败: %w", err)
	}

	if err := sqlDB.Close(); err != nil {
		return fmt.Errorf("关闭数据库连接失败: %w", err)
	}

	log.Println("✅ 数据库连接已关闭")
	return nil
}

// =====================================================
// 数据库健康检查
// =====================================================

// HealthCheck 检查数据库连接是否正常
func HealthCheck() error {
	if DB == nil {
		return fmt.Errorf("数据库未初始化")
	}

	sqlDB, err := DB.DB()
	if err != nil {
		return fmt.Errorf("获取数据库实例失败: %w", err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := sqlDB.PingContext(ctx); err != nil {
		return fmt.Errorf("数据库连接异常: %w", err)
	}

	return nil
}

// =====================================================
// 数据库统计信息
// =====================================================

// GetStats 获取数据库连接池统计信息
func GetStats() (map[string]interface{}, error) {
	if DB == nil {
		return nil, fmt.Errorf("数据库未初始化")
	}

	sqlDB, err := DB.DB()
	if err != nil {
		return nil, fmt.Errorf("获取数据库实例失败: %w", err)
	}

	stats := sqlDB.Stats()

	return map[string]interface{}{
		"max_open_connections": stats.MaxOpenConnections,  // 最大打开连接数
		"open_connections":     stats.OpenConnections,     // 当前打开连接数
		"in_use":              stats.InUse,                // 正在使用的连接数
		"idle":                stats.Idle,                 // 空闲连接数
		"wait_count":          stats.WaitCount,            // 等待连接的总次数
		"wait_duration":       stats.WaitDuration.String(), // 等待连接的总时间
		"max_idle_closed":     stats.MaxIdleClosed,        // 因超过最大空闲数而关闭的连接数
		"max_lifetime_closed": stats.MaxLifetimeClosed,    // 因超过最大生存时间而关闭的连接数
	}, nil
}
